home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-02-18 | 56.4 KB | 1,875 lines |
- Path: news.larc.nasa.gov!amiga-request
- From: amiga-request@ab20.larc.nasa.gov (Amiga Sources/Binaries Moderator)
- Subject: v91i013: DiffDir 2.0 - directory comparison utility, Part01/01
- Reply-To: mrr@mrsoft.Newport.RI.US (Mark Rinfret)
- Newsgroups: comp.sources.amiga
- Message-ID: <comp.sources.amiga:v91i013@ab20.larc.nasa.gov>
- Date: 18 Feb 91 20:58:42 GMT
- Approved: tadguy@uunet.UU.NET (Tad Guy)
- X-Mail-Submissions-To: amiga@uunet.uu.net
- X-Post-Discussions-To: comp.sys.amiga.misc
-
- Submitted-by: mrr@mrsoft.Newport.RI.US (Mark Rinfret)
- Posting-number: Volume 91, Issue 013
- Archive-name: utilities/diffdir-2.0/part01
-
- This is DiffDir Version 2.0, an AmigaDOS directory comparison utility.
- DiffDir will scan two directories and generate a report describing all
- differences encountered. In addition, DiffDir will optionally do a
- binary file compare on files which otherwise seem to be the same. A
- user-customizable file comparison script can optionally be generated,
- inserting the user's favorite file-comparison command. Source,
- documentation, and a two test directory hierarchies are included.
-
-
-
- #!/bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 1 (of 1)."
- # Contents: DiffDir.c MRDates.c MRDates.h dir1 dir1/File1 dir1/File3
- # dir1/Level2 dir1/Level2/File1 dir1/Level2/File3 dir1/Level2/Level3
- # dir1/Level2/Level3/File1 dir1/Level2/Level3/File2
- # dir1/Level2/Level3/File3 dir1/file2 dir2 dir2/DifferentType
- # dir2/File1 dir2/File2 dir2/Level2 dir2/Level2/File1
- # dir2/Level2/File2 dir2/Level2/File3 dir2/Level2/Level3
- # dir2/Level2/Level3/File2 dir2/Level2/Level3/File3 dir2/file3
- # makefile
- # Wrapped by tadguy@ab20 on Mon Feb 18 15:58:36 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'DiffDir.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'DiffDir.c'\"
- else
- echo shar: Extracting \"'DiffDir.c'\" \(27265 characters\)
- sed "s/^X//" >'DiffDir.c' <<'END_OF_FILE'
- X/* DiffDir - Compare directories for differences.
- X Filename: DiffDir.c
- X
- X (C)Copyright 1988-1991 by Mark R. Rinfret, All Rights Reserved.
- X This software may be freely distributed for non-profit use only.
- X You are free to make changes and redistribute this program as
- X long as the source is distributed and this notice is kept intact.
- X
- X History (most recent change first):
- X
- X 02/15/91 V2.0 (MRR)
- X Oh, what the hey! Let's really change things! There are lots of
- X internal as well as external differences. Read the docs :-).
- X
- X 02/09/91 V1.2 (MRR)
- X Added -b flag (binary file compare)
- X
- X 07/04/89 V1.1 (MRR)
- X Added flags for specific tests.
- X
- X 12/31/88 V1.0 (MRR)
- X Program conception and implementation.
- X
- X I wrote DiffDir to assist me with configuration management. Though
- X I keep all of my PD files on floppy disk, I usually roll them onto
- X the hard disk when I want to make changes. Sometimes, I forget to
- X copy the hard disk version back to floppy or I forget that I've already
- X done it. DiffDir scans two directories and reports the following
- X discrepancies:
- X
- X 1. File dates are different.
- X 2. File protection flags are different.
- X 3. File names are not exact (case discrepancy).
- X 4. File sizes are different.
- X 5. File comments are different.
- X 6. File exists in one directory but not the other.
- X 7. File contents differ.
- X
- X See the Usage() function for command line options.
- X
- X*/
- X
- X#include <stdio.h>
- X#include <stdlib.h>
- X#include <string.h>
- X#include <ctype.h>
- X#include <fcntl.h>
- X#include <exec/types.h>
- X#include <exec/memory.h>
- X#include <libraries/dos.h>
- X#include <functions.h>
- X#include "MRDates.h"
- X
- Xchar *version = "DiffDir 2.0, Mark R. Rinfret, 02/15/91\n";
- X
- Xtypedef struct fileList {
- X USHORT fileCount;
- X char *dName; /* directory name for this list */
- X struct fileNode *firstEntry, *lastEntry;
- X } FileList;
- X
- Xtypedef struct fileNode {
- X struct fileNode *next, *prev;
- X struct fileList *parentList; /* the list that I belong to */
- X char *name;
- X LONG flags; /* protection, other bits */
- X char *comment; /* NULL if comment was empty */
- X struct DateStamp date;
- X ULONG size; /* in bytes */
- X BOOL isDir; /* TRUE => node is a directory */
- X struct FileNode *subList; /* sublist for directory node */
- X } FileNode;
- X
- X#define NAMES_DONT_MATCH 1
- X#define DATES_DONT_MATCH 2
- X#define FLAGS_DONT_MATCH 4
- X#define SIZES_DONT_MATCH 8
- X#define COMMENTS_DONT_MATCH 16
- X
- X#define ITEM_COUNT 5 /* Make sure this tracks the list above! */
- X
- Xstatic char *errorDesc[ITEM_COUNT] = {
- X " names ", " dates ", " flags ", " sizes ", " comments " };
- X
- X/* The scriptCmd is inserted into the command string output to the optional
- X * comparison script. It may be over-ridden by the user.
- X */
- Xchar scriptCmd[128] = "cmp";
- X
- Xvoid AddNode(FileNode *node, FileList *list);
- Xint CollectFiles(FileList *list);
- Xint CompareDirs(FileList *list1, FileList *list2);
- Xvoid CompareFileContents(FileNode *f1, FileNode *f2);
- Xint CompareFiles(FileList *l1, FileList *l2);
- Xint CompareLists(FileList *l1, FileList *l2);
- Xchar *DupString(const char *oldString);
- XFileNode *FindFile(FileNode *node, FileList *list);
- Xvoid FreeNode(FileNode *node, FileList *list);
- Xchar *MakeDirName(const char *s1, const char *s2);
- Xvoid *MyAlloc(size_t size);
- Xvoid MyExit(int code);
- Xvoid MyFree(void *ptr);
- Xint OpenFile(FileNode *f);
- Xvoid ReportStats(void);
- Xint stricmp(const char *s1, const char *s2);
- Xvoid Usage(void);
- Xvoid WriteFileInfo(FileNode *node);
- X
- X
- Xint checkContents = TRUE;
- Xstruct FileInfoBlock *fib;
- XBOOL ignoreCase = FALSE;
- XUSHORT level = 0;
- XFileList list1, list2;
- XLONG maxMemUsed, memInUse;
- XBOOL outputScript = FALSE;
- XFILE *scriptFile;
- XULONG testFlags = 0;
- XLONG totalFiles, totalDirs;
- XBOOL verbose = FALSE;
- X
- Xmain(argc, argv)
- X int argc; char **argv;
- X{
- X int leng;
- X char *ptr;
- X
- X testFlags = 0xFFFFFFFF;
- X
- X while (--argc > 0 && **++argv == '-') {
- X ptr = &argv[0][1];
- X leng = strlen(ptr);
- X if (leng < 5) {
- X Usage();
- X }
- X if (strncmp("nocontents", ptr, leng) == 0) {
- X /* Compare file contents. */
- X checkContents = FALSE;
- X } else if (strncmp(ptr, "nocomments", leng) == 0) {
- X /* Ignore comments. */
- X testFlags &= (~COMMENTS_DONT_MATCH);
- X } else if (strncmp(ptr, "nodates", leng) == 0) {
- X /* Suppress date test. */
- X testFlags &= (~DATES_DONT_MATCH);
- X } else if (strncmp(ptr, "noflags", leng) == 0) {
- X /* Ignore flags (protection word). */
- X testFlags &= (~FLAGS_DONT_MATCH);
- X } else if (strncmp(ptr, "nosizes", leng) == 0) {
- X testFlags &= (~SIZES_DONT_MATCH);
- X } else if (strncmp(ptr, "nocase", leng) == 0) {
- X /* Ignore filename case. */
- X ignoreCase = TRUE;
- X } else if (strncmp(ptr, "script", leng) == 0) {
- X if (--argc) {
- X ++argv;
- X scriptFile = fopen(*argv, "w");
- X if (!scriptFile) {
- X perror("Script file would not open!");
- X exit(20);
- X }
- X }
- X } else if (strncmp(ptr, "command", leng) == 0) {
- X if (--argc) {
- X ++argv;
- X strcpy(scriptCmd, *argv);
- X }
- X else
- X Usage();
- X } else if (strncmp(ptr, "verbose", leng) == 0) {
- X verbose = TRUE;
- X } else {
- X Usage();
- X }
- X }
- X if (argc != 2) Usage();
- X list1.dName = MakeDirName("",*argv++);
- X list2.dName = MakeDirName("",*argv);
- X fib = MyAlloc(sizeof(*fib));
- X if (fib == NULL) {
- X printf("DiffDir: unable to allocate file info block!\n");
- X goto done;
- X }
- X
- X if (! CollectFiles(&list1))
- X if (! CollectFiles(&list2))
- X CompareLists(&list1, &list2);
- Xdone:
- X if (fib) MyFree(fib);
- X if (verbose) ReportStats();
- X}
- X
- X/* FUNCTION
- X AddNode - add file info node to list.
- X
- X SYNOPSIS
- X AddNode(FileNode *node, FileList *list);
- X
- X DESCRIPTION
- X AddNode adds the <node> to the <list>. Right now, a very lazy
- X approach is taken (adds to end of list). Perhaps later, we'll
- X make the list a binary tree or better.
- X
- X*/
- X
- Xvoid
- XAddNode(FileNode *node, FileList *list)
- X{
- X if (list->firstEntry) { /* List has stuff in it? */
- X list->lastEntry->next = node;
- X }
- X else {
- X list->firstEntry = node; /* This is the first entry. */
- X }
- X node->prev = list->lastEntry;
- X list->lastEntry = node;
- X ++list->fileCount;
- X if (node->isDir)
- X ++totalDirs;
- X else
- X ++totalFiles;
- X}
- X
- X/* FUNCTION
- X CollectFiles - collect files for one directory level.
- X
- X SYNOPSIS
- X int CollectFiles(FileList *list);
- X
- X DESCRIPTION
- X CollectFiles scans the directory pointed to by <list> and creates
- X list entry nodes for each file or directory found. A zero is
- X returned on success, non-zero otherwise.
- X*/
- X
- Xint
- XCollectFiles(FileList *list)
- X{
- X int errCode;
- X BPTR lock = 0;
- X FileNode *fNode = NULL;
- X int result = 0;
- X
- X if (verbose)
- X printf("DiffDir: scanning '%s'\n", list->dName);
- X
- X lock = Lock(list->dName, SHARED_LOCK);
- X if (lock == 0) {
- X result = IoErr();
- X printf("DiffDir: failed to lock '%s'!\n", list->dName);
- X goto done;
- X }
- X if (Examine(lock, fib) == 0) {
- X result = IoErr();
- X printf("DiffDir: failed to get info for '%s'!\n", list->dName);
- X goto done;
- X }
- X
- X if (fib->fib_DirEntryType < 0) {
- X result = -1;
- X printf("DiffDir: '%s' is not a directory!\n", list->dName);
- X goto done;
- X }
- X
- X while (!result && ExNext(lock, fib)) {
- X fNode = MyAlloc(sizeof(FileNode));
- X fNode->parentList = list;
- X fNode->name = DupString(fib->fib_FileName);
- X fNode->isDir = (fib->fib_DirEntryType > 0);
- X fNode->flags = fib->fib_Protection;
- X if (*fib->fib_Comment)
- X fNode->comment = DupString(fib->fib_Comment);
- X fNode->date = fib->fib_Date;
- X fNode->size = fib->fib_Size;
- X AddNode(fNode, list);
- X }
- X errCode = IoErr();
- X if (errCode != ERROR_NO_MORE_ENTRIES) {
- X result = errCode;
- X printf("DiffDir: scan of directory '%s' failed!\n", list->dName);
- X }
- Xdone:
- X if (lock) UnLock(lock);
- X return result;
- X}
- X
- X/* FUNCTION
- X CompareLists - compare files and directories in two lists.
- X
- X SYNOPSIS
- X int CompareLists(FileList *l1, FileList *l2);
- X
- X DESCRIPTION
- X Comparelists first makes an overall assessment of lists <l1> and
- X <l2>. If the number of files/directories in the lists differ,
- X that fact is reported. Next, CompareLists tests for the condition
- X where an entry in one list has the same name as an entry in the
- X other list, but one entry represents a file and the other entry
- X represents a directory. These entries are removed from the list.
- X CompareFiles is then called to compare all file nodes, removing
- X them as they are "used". Finally, CompareDirs is called to
- X compare all directory nodes, again removing the nodes as they
- X are used. A non-zero return indicates a fatal error.
- X*/
- Xint
- XCompareLists(FileList *l1, FileList *l2)
- X{
- Xstatic char *isDirMsg = " is a directory";
- Xstatic char *isFileMsg = " is a file";
- X
- X FileNode *f1, *f2, *nextEntry;
- X int result = 0;
- X
- X ++level;
- X if (verbose) {
- X printf("DiffDir: comparing directory\n '%s' to '%s'\n",
- X l1->dName, l2->dName);
- X }
- X /* Scan the lists for nodes whose names match but whose types
- X differ (file vs. directory).
- X */
- X for (f1 = l1->firstEntry; f1; f1 = nextEntry) {
- X nextEntry = f1->next;
- X f2 = FindFile(f1, l2);
- X if (f2 && (f2->isDir != f1->isDir) ) { /* Ooops! */
- X printf("*** '%s%s' %s\n*** but '%s%s' %s!\n",
- X l1->dName,f1->name, f1->isDir ? isDirMsg : isFileMsg,
- X l2->dName,f2->name, f2->isDir ? isDirMsg : isFileMsg);
- X FreeNode(f1, l1);
- X FreeNode(f2, l2);
- X }
- X }
- X if (! (result = CompareFiles(l1, l2)))
- X result = CompareDirs(l1, l2);
- X --level;
- X return result;
- X}
- X
- X/* FUNCTION
- X CompareDirs - compare directory entries.
- X
- X SYNOPSIS
- X int CompareDirs(FileList *list1, FileList *list2);
- X
- X DESCRIPTION
- X CompareDirs scans <list1>, attempting to match its directory node
- X entries with entries in <list2>. For each matching entry found,
- X CompareDirs creates a new sublist, recursively calling CompareLists
- X to compare the contents of those directories. When CompareLists
- X returns, CompareDirs removes the "used" directory entries from
- X both lists. A non-zero return code indicates a fatal error.
- X*/
- X
- Xint
- XCompareDirs(FileList *list1, FileList *list2)
- X{
- Xstatic char *missing = "*** Directory missing: '%s%s'\n";
- X
- X FileNode *n1, *n2, *nextEntry;
- X int result = 0;
- X FileList *subList1, *subList2;
- X
- X for (n1 = list1->firstEntry; n1 && !result; n1 = nextEntry) {
- X nextEntry = n1->next;
- X /* Note: there should only be directory nodes in the list
- X at this point!
- X */
- X if (! n1->isDir) {
- X puts("DiffDir: non-directory node found in CompareDirs!");
- X MyExit(20); /* What else can we do? */
- X }
- X n2 = FindFile(n1, list2);
- X if (n2 == NULL) {
- X printf(missing, list2->dName, n1->name);
- X }
- X else {
- X subList1 = MyAlloc( sizeof(FileList) );
- X subList1->dName = MakeDirName(list1->dName, n1->name);
- X subList2 = MyAlloc( sizeof(FileList) );
- X subList2->dName = MakeDirName(list2->dName, n2->name);
- X result = CollectFiles(subList1);
- X if (!result)
- X result = CollectFiles(subList2);
- X if (!result)
- X result = CompareLists(subList1, subList2);
- X
- X /* Give back the memories :-) */
- X MyFree(subList1->dName);
- X MyFree(subList1);
- X MyFree(subList2->dName);
- X MyFree(subList2);
- X }
- X FreeNode(n1, list1);
- X if (n2) FreeNode(n2, list2);
- X }
- X if (!result) {
- X for (n2 = list2->firstEntry; n2; n2 = nextEntry) {
- X nextEntry = n2->next;
- X printf(missing, list1->dName, n2->name);
- X FreeNode(n2, list2);
- X }
- X }
- X return result;
- X}
- X
- X/* FUNCTION
- X CompareFile - compare the attributes of two similar files.
- X
- X SYNOPSIS
- X void CompareFile(FileNode *f1, FileNode *f2);
- X
- X DESCRIPTION
- X CompareFile is called with two file description nodes, <f1> and
- X <f2> which are expected to represent similar files in different
- X directory hierarchies. CompareFile compares the currently selected
- X file attributes and will report any discrepancies to standard output.
- X*/
- Xvoid
- XCompareFile(FileNode *f1, FileNode *f2)
- X{
- X USHORT error = 0, item, mask;
- X
- X if (f1->isDir != f2->isDir) {
- X puts("*** File type mismatch (file vs. dir) - program error!");
- X FreeNode(f1, f1->parentList);
- X FreeNode(f2, f2->parentList);
- X }
- X else {
- X if ((testFlags & FLAGS_DONT_MATCH) && (f1->flags != f2->flags) )
- X error |= FLAGS_DONT_MATCH;
- X
- X if ((testFlags & DATES_DONT_MATCH) &&
- X (CompareDS( (long *) &f1->date, (long *) &f2->date) ) )
- X error |= DATES_DONT_MATCH;
- X
- X if (!ignoreCase) {
- X if (strcmp(f1->name, f2->name) != 0)
- X error |= NAMES_DONT_MATCH;
- X }
- X
- X if ( (testFlags & SIZES_DONT_MATCH) && (f1->size != f2->size) ) {
- X error |= SIZES_DONT_MATCH;
- X }
- X
- X /* Do we want to compare all files? */
- X
- X if (scriptFile) {
- X fprintf(scriptFile, "%s %s%s %s%s\n",
- X scriptCmd,
- X f1->parentList->dName,f1->name,
- X f2->parentList->dName,f2->name);
- X }
- X
- X if ((testFlags & COMMENTS_DONT_MATCH) &&
- X (strcmp(f1->comment, f2->comment) != 0) )
- X error |= COMMENTS_DONT_MATCH;
- X }
- X
- X if (error) { /* Aw, darn... */
- X printf("*** Mismatch: ");
- X for (item = 0, mask = 1; item < ITEM_COUNT;
- X ++item, mask= (mask << 1)) {
- X if (error & mask)
- X printf(errorDesc[item]);
- X }
- X puts("");
- X puts(f1->parentList->dName);
- X WriteFileInfo(f1);
- X puts("------------------------------------");
- X puts(f2->parentList->dName);
- X WriteFileInfo(f2);
- X puts("====================================");
- X }
- X if (checkContents && (f1->size == f2->size) ) {
- X CompareFileContents(f1, f2);
- X }
- X}
- X
- X
- X/* FUNCTION
- X * CompareFileContents - do a binary comparison of two files.
- X *
- X * SYNOPSIS
- X * void CompareFileContents(FileNode *f1, FileNode *f2);
- X *
- X * DESCRIPTION
- X * This function performs a byte-by-byte comparison of two files,
- X * terminating with an error message on the first mismatch.
- X */
- Xvoid
- XCompareFileContents(FileNode *f1, FileNode *f2)
- X{
- X#define BUFFER_SIZE 32768
- X
- X static char *readErr = "Read error on file '%s%s'\n";
- X
- X int fd1 = -1, fd2 = -1;
- X char *buf1 = NULL, *buf2 = NULL;
- X size_t i;
- X size_t leng1, leng2;
- X
- X buf1 = MyAlloc(BUFFER_SIZE);
- X buf2 = MyAlloc(BUFFER_SIZE);
- X
- X fd1 = OpenFile(f1);
- X if (fd1 == -1) goto done;
- X
- X fd2 = OpenFile(f2);
- X if (fd2 == -1) goto done;
- X
- X while (1) {
- X leng1 = read(fd1, buf1, BUFFER_SIZE);
- X leng2 = read(fd2, buf2, BUFFER_SIZE);
- X if (leng1 == -1) {
- X printf(readErr,f1->parentList->dName,f1->name);
- X goto done;
- X }
- X if (leng2 == -1) {
- X printf(readErr,f2->parentList->dName, f2->name);
- X goto done;
- X }
- X if (leng1 != leng2) {
- X printf("File length mismatch: '%s%s' vs. '%s%s'\n",
- X f1->parentList->dName,f1->name,
- X f2->parentList->dName,f2->name);
- X }
- X for (i = 0; i < leng1; ++i) {
- X if (buf1[i] != buf2[i]) {
- X printf(
- X "*** File data mismatch at byte %d:\n '%s%s' vs. '%s%s'\n",
- X i,
- X f1->parentList->dName,f1->name,
- X f2->parentList->dName,f2->name);
- X goto done;
- X }
- X }
- X if (leng1 < BUFFER_SIZE) break; /* End of file? */
- X }
- X
- Xdone:
- X if (buf1) MyFree(buf1);
- X if (buf2) MyFree(buf2);
- X if (fd1 != -1) close(fd1);
- X if (fd2 != -1) close(fd2);
- X}
- X
- X/* FUNCTION
- X CompareFiles - compare all file nodes in two lists.
- X
- X SYNOPSIS
- X int CompareFiles(FileList *l1, FileList *l2);
- X
- X DESCRIPTION
- X The file attributes for all files in list <l1> are compared to
- X those in list <l2>. Discrepancies are reported to standard
- X output. After all the files in <l1> have been tested, a second
- X scan is made over list <l2> for any remaining file nodes. These
- X represent files which were not found in <l1>. Upon return, all
- X file nodes will have been removed from lists <l1> and <l2>,
- X leaving behind any directory nodes for CompareDirs().
- X*/
- X
- Xint
- XCompareFiles(FileList *l1, FileList *l2)
- X{
- X static char *missing = "*** File missing: '%s%s'\n";
- X FileNode *f1, *f2, *nextNode;
- X
- X /* Loop through all file entries in list1. Since the list may be
- X * modified along the way, save a look-ahead pointer to the next
- X * entry.
- X */
- X
- X for (f1 = l1->firstEntry; f1; f1 = nextNode) {
- X nextNode = f1->next;
- X if (f1->isDir) continue;
- X f2 = FindFile(f1, l2);
- X if (f2 == NULL) {
- X printf(missing, l2->dName, f1->name);
- X }
- X else {
- X CompareFile(f1, f2);
- X }
- X FreeNode(f1, l1);
- X if (f2)
- X FreeNode(f2, l2);
- X }
- X
- X /* Look for "leftovers" in list 2. */
- X
- X for (f2 = l2->firstEntry; f2; f2 = nextNode) {
- X nextNode = f2->next;
- X if (f2->isDir) continue;
- X printf(missing, l1->dName, f2->name);
- X FreeNode(f2, l2);
- X }
- X return 0;
- X}
- X
- X/* FUNCTION
- X DupString - duplicate a string.
- X
- X SYNOPSIS
- X char *DupString(const char *oldString);
- X
- X DESCRIPTION
- X DupString dynamically allocates space for a new copy of <oldString>,
- X copies <oldString> to the new area and returns a pointer to the new
- X string.
- X
- X*/
- X
- Xchar *
- XDupString(const char *oldString)
- X{
- X char *newString;
- X
- X newString = MyAlloc(strlen(oldString)+1);
- X strcpy(newString, oldString);
- X return newString;
- X}
- X
- X/* FUNCTION
- X FindFile - find a file node by name.
- X
- X SYNOPSIS
- X FileNode *FindFile(FileNode *node, FileNode *list)
- X
- X DESCRIPTION
- X FindFile searches <list> for a file description node whose name
- X matches the name in <node>. A case-insensitive name comparison
- X is performed. If the matching entry is found, a pointer to it
- X is returned. Otherwise, NULL is returned.
- X*/
- X
- XFileNode *
- XFindFile(FileNode *node, FileList *list)
- X{
- X FileNode *tNode;
- X
- X for (tNode = list->firstEntry; tNode; tNode = tNode->next) {
- X if (stricmp(node->name, tNode->name) == 0)
- X return tNode;
- X }
- X return NULL; /* Sorry...not found. */
- X}
- X
- X/* FUNCTION
- X FreeNode - free a file node from a list.
- X
- X SYNOPSIS
- X void FreeNode(node, list)
- X FileNode *node;
- X FileList *list;
- X*/
- Xvoid
- XFreeNode(FileNode *node, FileList *list)
- X{
- X if (node->prev)
- X node->prev->next = node->next;
- X if (node->next)
- X node->next->prev = node->prev;
- X if (node == list->firstEntry)
- X list->firstEntry = node->next;
- X if (node == list->lastEntry)
- X list->lastEntry = node->prev;
- X
- X MyFree(node->name);
- X MyFree(node->comment);
- X MyFree(node);
- X}
- X
- X/* FUNCTION
- X MakeDirName - assemble a directory name from components.
- X
- X SYNOPSIS
- X char *MakeDirName(const char *s1, const char *s2);
- X
- X DESCRIPTION
- X MakeDirName dynamically allocates a string large enough to hold
- X a composite name formed from strings <s1> and <s2>. It also adds
- X a directory separator (/) to the end of the new name if the
- X new result does not end in a colon (:). The new name is returned
- X as the function result.
- X*/
- Xchar *
- XMakeDirName(const char *s1, const char *s2)
- X{
- X char *dirName;
- X
- X dirName = MyAlloc(strlen(s1)+strlen(s2)+2);
- X strcpy(dirName, s1);
- X strcat(dirName, s2);
- X if (dirName[strlen(dirName)-1] != ':') strcat(dirName, "/");
- X return dirName;
- X}
- X
- X/* FUNCTION
- X MyAlloc - perform memory allocation with error checking.
- X
- X SYNOPSIS
- X void *MyAlloc(size_t size);
- X
- X DESCRIPTION
- X MyAlloc attempts to allocate <size> bytes of memory. If it fails,
- X an error message is sent to standard output and the program is
- X terminated. Otherwise, MyAlloc returns a pointer to the newly
- X allocated (zero-filled) memory block.
- X*/
- Xvoid *
- XMyAlloc(size_t size)
- X{
- X
- X long *ptr;
- X
- X size += 4; /* Add word for size tracking. */
- X ptr = AllocMem(size, MEMF_CLEAR | MEMF_PUBLIC);
- X if (ptr == NULL) {
- X printf("DiffDir: failed to allocate %ld bytes!\n", size);
- X MyExit(20);
- X }
- X *ptr = size; /* Store size. */
- X ++ptr; /* Advance pointer to data block. */
- X memInUse += size;
- X if (memInUse > maxMemUsed) maxMemUsed = memInUse;
- X return (void *) ptr;
- X}
- X
- X/* FUNCTION
- X MyExit - terminate program with cleanup.
- X
- X SYNOPSIS
- X void MyExit(int code);
- X
- X DESCRIPTION
- X MyExit simply provides a graceful way for the program to exit,
- X performing any necessary cleanup chores.
- X*/
- Xvoid
- XMyExit(int code)
- X{
- X if (fib) MyFree(fib);
- X ReportStats();
- X exit(code);
- X}
- X
- X
- X/* FUNCTION
- X * MyFree - free memory block, tracking memory usage.
- X *
- X * SYNOPSIS
- X * void MyFree(void *);
- X *
- X * DESCRIPTION
- X * MyFree releases a block of memory allocated by MyAlloc. It
- X * also safeguards against null pointers.
- X */
- X
- Xvoid MyFree(void * ptr)
- X{
- X long size;
- X long *xptr;
- X
- X if (ptr) { /* Ignore null pointers. */
- X xptr = (long *)ptr;
- X --xptr;
- X size = *xptr;
- X FreeMem(xptr, size);
- X memInUse -= size;
- X }
- X}
- X
- X/* FUNCTION
- X * OpenFile - open a file for read-only access.
- X *
- X * SYNOPSIS
- X * int OpenFile(FileNode *f);
- X *
- X * DESCRIPTION
- X * OpenFile opens a file for non-buffered I/O. It returns a file
- X * descriptor which is -1 if the file fails to open
- X */
- X
- Xint
- XOpenFile(FileNode *f)
- X{
- X int fd;
- X char fileName[256];
- X
- X strcpy(fileName, f->parentList->dName);
- X strcat(fileName, f->name);
- X fd = open(fileName, O_RDONLY);
- X if (fd == -1) {
- X printf("** Failed to open file: '%s'\n", fileName);
- X }
- X return fd;
- X}
- X
- X/* FUNCTION
- X ReportStats - report program statistics.
- X
- X SYNOPSIS
- X void ReportStats(void);
- X
- X DESCRIPTION
- X ReportMem reports the maximum memory used, total number of file
- X nodes and total number of directory nodes for this invocation
- X of DiffDir, ONLY if the verbose option is turned on or if the
- X program terminates abnormally.
- X*/
- Xvoid
- XReportStats(void)
- X{
- X printf("DiffDir: Files: %ld; directories: %ld; max memory usage: %ld bytes\n",
- X totalFiles, totalDirs, maxMemUsed);
- X}
- X
- X
- X/* FUNCTION
- X stricmp - perform a case-insensitive string compare.
- X
- X SYNOPSIS
- X int stricmp(const char *s1, const char *s2);
- X
- X DESCRIPTION
- X Strings <s1> and <s2> are compared, ignoring differences in case.
- X A result code is returned according to the following:
- X 0 => strings match
- X <0 => s1 < s2
- X >0 => s1 > s2
- X*/
- X
- Xint
- Xstricmp(const char *s1, const char *s2)
- X{
- X int c1, c2, cd;
- X
- X do {
- X c1 = tolower(*s1++);
- X c2 = tolower(*s2++);
- X if (cd = (c1 - c2)) break;
- X } while (c1 && c2);
- X
- X return cd;
- X}
- X
- X/* FUNCTION
- X Usage - describe program usage and exit.
- X
- X SYNOPSIS
- X void Usage(void);
- X
- X DESCRIPTION
- X Usage is called when the user invokes DiffDir with incorrect
- X or insufficient parameters. The correct invocation syntax
- X is displayed and the program is terminated.
- X*/
- Xvoid
- XUsage(void)
- X{
- X puts(version);
- X puts(
- X"Usage: DiffDir [ options ] dir1 dir2\n"
- X" where options may be:\n"
- X" -nocase ignore filename case differences\n"
- X" -nocomments ignore comment (filenote) differences\n"
- X" -nocontents don't compare file contents when sizes are equal\n"
- X" -nodates ignore creation/modification date differences\n"
- X" -noflags ignore flag (protection word) differences\n"
- X" -nosizes ignore file sizes (dumb, but if you need to...)\n"
- X" -script <scriptfile> generate a comparison script (name = scriptfile)\n"
- X" -command <string> use <string> to create script commands\n"
- X" -verbose generate verbose output\n"
- X "\n");
- X
- X MyExit(20);
- X}
- X
- X/* FUNCTION
- X WriteFileInfo - write a full file description to standard output.
- X
- X SYNOPSIS
- X void WriteFileInfo(FileNode *node);
- X
- X DESCRIPTION
- X WriteFileInfo writes complete info about the file specified by
- X <node> to the standard output. This only happens when an error
- X occurs.
- X
- X*/
- X
- Xvoid
- XWriteFileInfo(FileNode *node)
- X{
- X static char flagSetNames[9] = {
- X '-', '-', '-', '-', 'a', 'p', 's', 'h', 'C'
- X };
- X static char flagClearNames[9] = {
- X 'd', 'e', 'w', 'r', '-', '-', '-', '-', '-'
- X };
- X
- X ULONG flags;
- X SHORT i;
- X ULONG mask;
- X char temp[30];
- X
- X DSToStr(temp,"%02m-%02d-%02y %02h:%02n:%02s ", (long *) &node->date);
- X printf(temp);
- X flags = node->flags;
- X for (i = 0, mask = 1; i < 9; ++i, mask = (mask << 1) )
- X if (flags & mask)
- X temp[8 - i] = flagSetNames[i];
- X else
- X temp[8 - i] = flagClearNames[i];
- X
- X temp[9] = '\0';
- X
- X printf("%s %8ld %s\n", temp, node->size, node->name);
- X if (node->comment)
- X printf(": %s\n",node->comment);
- X}
- END_OF_FILE
- if test 27265 -ne `wc -c <'DiffDir.c'`; then
- echo shar: \"'DiffDir.c'\" unpacked with wrong size!
- fi
- # end of 'DiffDir.c'
- fi
- if test -f 'MRDates.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'MRDates.c'\"
- else
- echo shar: Extracting \"'MRDates.c'\" \(15280 characters\)
- sed "s/^X//" >'MRDates.c' <<'END_OF_FILE'
- X/*
- X MRDates - AmigaDOS date support routines.
- X 07/03/88
- X
- X This package is a hybrid of code from Thad Floryan, Doug Merrit and
- X myself. I wanted a reliable set of AmigaDOS date conversion routines
- X and this combination seems to work pretty well. The star of the show
- X here is Thad's algorithm for converting the "days elapsed" field of
- X an AmigaDOS DateStamp, using an intermediate Julian date format. I
- X lifted/embellished some of the data structures from Doug's ShowDate
- X package and wrote the DateToDS function.
- X
- X History: (most recent change first)
- X
- X 12/31/88 -MRR-
- X StrToDS was not handling the null string properly.
- X
- X 11/01/88 -MRR- Added Unix-style documentation.
- X
- X 07/03/88 - Changed some names:
- X Str2DS => StrToDS
- X DS2Str => DSToStr
- X */
- X
- X#define MRDATES
- X#include "MRDates.h"
- X#include <exec/types.h>
- X#include <stdio.h>
- X#include <ctype.h>
- X#include <string.h>
- X
- X
- X#define DATE_SEPARATORS "/:-."
- X#define MINS_PER_HOUR 60
- X#define SECS_PER_MIN 60
- X#define SECS_PER_HOUR (SECS_PER_MIN * MINS_PER_HOUR)
- X#define TICS_PER_SEC 50
- X
- X#define YEARS_PER_CENTURY 100
- X
- X
- X/*
- X definitions to calculate current date
- X */
- X#define FEB 1 /* index of feb. in table (for leap years) */
- X#define DAYS_PER_WEEK 7
- X#define DAYS_PER_YEAR 365
- X#define YEARS_PER_LEAP 4
- X#define START_YEAR 1978
- X#define FIRST_LEAP_YEAR 1980
- X#define LEAP_ADJUST (FIRST_LEAP_YEAR - START_YEAR)
- X#define LEAP_FEB_DAYS 29
- X#define NORM_FEB_DAYS 28
- X#define IsLeap(N) (((N) % YEARS_PER_LEAP) ? 0 : 1)
- X
- X
- X/* FUNCTION
- X DSToDate - convert a DateStamp to a DATE.
- X
- X SYNOPSIS
- X int DSToDate(dateStamp, date)
- X struct DateStamp *dateStamp;
- X DATE *date;
- X
- X DESCRIPTION
- X Extracts the date components from an AmigaDOS datestamp.
- X The calculations herein use the following assertions:
- X
- X 146097 = number of days in 400 years per 400 * 365.2425 = 146097.00
- X 36524 = number of days in 100 years per 100 * 365.2425 = 36524.25
- X 1461 = number of days in 4 years per 4 * 365.2425 = 1460.97
- X
- X AUTHOR
- X Thad Floryan, 12-NOV-85
- X Mods by Mark Rinfret, 04-JUL-88
- X
- X SEE ALSO
- X Include file MRDates.h.
- X
- X */
- X
- X#define DDELTA 722449 /* days from Jan.1,0000 to Jan.1,1978 */
- X
- Xstatic int mthvec[] =
- X {-1, -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364};
- X
- Xint
- XDSToDate(ds, date)
- X long *ds; DATE *date;
- X
- X{
- X
- X long jdate, day0, day1, day2, day3;
- X long year, month, day, temp;
- X
- X jdate = ds[0] + DDELTA; /* adjust internal date to Julian */
- X
- X year = (jdate / 146097) * 400;
- X day0 = day1 = jdate %= 146097;
- X year += (jdate / 36524) * 100;
- X day2 = day1 %= 36524;
- X year += (day2 / 1461) * 4;
- X day3 = day1 %= 1461;
- X year += day3 / 365;
- X month = 1 + (day1 %= 365);
- X day = month % 30;
- X month /= 30;
- X
- X if ( ( day3 >= 59 && day0 < 59 ) ||
- X ( day3 < 59 && (day2 >= 59 || day0 < 59) ) )
- X ++day1;
- X
- X if (day1 > mthvec[1 + month]) ++month;
- X day = day1 - mthvec[month];
- X date->Dyear = year;
- X date->Dmonth = month;
- X date->Dday = day;
- X date->Dweekday = ds[0] % DAYS_PER_WEEK;
- X
- X temp = ds[1]; /* get ds_Minute value */
- X date->Dhour = temp / MINS_PER_HOUR;
- X date->Dminute = temp % MINS_PER_HOUR;
- X date->Dsecond = ds[2] / TICS_PER_SEC;
- X return 0;
- X}
- X
- X/* FUNCTION
- X DateToDS(date, dateStamp)
- X
- X SYNOPSIS
- X void DateToDS(date, dateStamp)
- X DATE *date;
- X struct DateStamp *dateStamp;
- X
- X DESCRIPTION
- X DateToDS converts the special DATE format to a DateStamp.
- X */
- X
- XDateToDS(date, ds)
- X DATE *date; long *ds;
- X{
- X long daysElapsed, yearsElapsed, leapYears, thisMonth, thisDay, thisYear;
- X int month;
- X
- X /* Note the special handling for year < START_YEAR. In this case,
- X * the other fields are not even checked - the user just gets the
- X * "start of time".
- X */
- X if ((thisYear = date->Dyear) < START_YEAR) {
- X ds[0] = ds[1] = ds[2] = 0;
- X return;
- X }
- X if (IsLeap(thisYear))
- X calendar[FEB].Mdays = LEAP_FEB_DAYS;
- X
- X thisDay = date->Dday - 1;
- X thisMonth = date->Dmonth -1;
- X yearsElapsed = thisYear - START_YEAR;
- X leapYears = (yearsElapsed + LEAP_ADJUST -1) / YEARS_PER_LEAP;
- X daysElapsed = (yearsElapsed * DAYS_PER_YEAR) + leapYears;
- X for (month = 0; month < thisMonth; ++month)
- X daysElapsed += calendar[month].Mdays;
- X daysElapsed += thisDay;
- X calendar[FEB].Mdays = NORM_FEB_DAYS;
- X ds[0] = daysElapsed;
- X ds[1] = date->Dhour * MINS_PER_HOUR + date->Dminute;
- X ds[2] = date->Dsecond * TICS_PER_SEC;
- X}
- X/* FUNCTION
- X CompareDS - compare two DateStamp values.
- X
- X SYNOPSIS
- X int CompareDS(date1, date2)
- X struct DateStamp *date1, *date2;
- X
- X DESCRIPTION
- X CompareDS performs an ordered comparison between two DateStamp
- X values, returning the following result codes:
- X
- X -1 => date1 < date2
- X 0 => date1 == date2
- X 1 => date1 > date2
- X
- X NOTE:
- X This routine makes an assumption about the DateStamp structure,
- X specifically that it can be viewed as an array of 3 long integers
- X in days, minutes and ticks order.
- X */
- X
- Xint
- XCompareDS(d1, d2)
- X long *d1, *d2;
- X{
- X USHORT i;
- X long compare;
- X
- X for (i = 0; i < 3; ++i) {
- X if (compare = (d1[i] - d2[i])) {
- X if (compare < 0) return -1;
- X return 1;
- X }
- X }
- X return 0; /* dates match */
- X}
- X
- X/* FUNCTION
- X DSToStr - convert a DateStamp to a formatted string.
- X
- X SYNOPSIS
- X void DSToStr(str,fmt,d)
- X char *str, *fmt;
- X struct DateStamp *d;
- X
- X DESCRIPTION
- X DSToStr works a little like sprintf. It converts a DateStamp
- X to an ascii formatted string. The formatting style is dependent
- X upon the contents of the format string, fmt, passed to this
- X function.
- X
- X The content of the format string is very similar to that
- X for printf, with the exception that the following letters
- X have special significance:
- X y => year minus 1900
- X Y => full year value
- X m => month value as integer
- X M => month name
- X d => day of month (1..31)
- X D => day name ("Monday".."Sunday")
- X h => hour in twenty-four hour notation
- X H => hour in twelve hour notation
- X i => 12 hour indicator for H notation (AM or PM)
- X I => same as i
- X n => minutes (sorry...conflict with m = months)
- X N => same as n
- X s => seconds
- X S => same as s
- X
- X All other characters are passed through as part of the normal
- X formatting process. The following are some examples with
- X Saturday, July 18, 1987, 13:53 as an input date:
- X
- X "%y/%m/%d" => 87/7/18
- X "%02m/%02d/%2y" => 07/18/87
- X "%D, %M %d, %Y" => Saturday, July 18, 1987
- X "%02H:%02m i" => 01:53 PM
- X "Time now: %h%m" => Time now: 13:53
- X
- X */
- Xvoid
- XDSToStr(str,fmt,d)
- X char *str, *fmt; long *d;
- X{
- X DATE date;
- X char fc,*fs,*out;
- X USHORT ivalue;
- X char new_fmt[256]; /* make it big to be "safe" */
- X USHORT new_fmt_lng;
- X char *svalue;
- X
- X DSToDate(d, &date); /* convert DateStamp to DATE format */
- X
- X *str = '\0'; /* insure output is empty */
- X out = str;
- X fs = fmt; /* make copy of format string pointer */
- X
- X while (fc = *fs++) { /* get format characters */
- X if (fc == '%') { /* formatting meta-character? */
- X new_fmt_lng = 0;
- X new_fmt[new_fmt_lng++] = fc;
- X /* copy width information */
- X while (isdigit(fc = *fs++) || fc == '-')
- X new_fmt[new_fmt_lng++] = fc;
- X
- X switch (fc) { /* what are we trying to do? */
- X case 'y': /* year - 1980 */
- X ivalue = date.Dyear % 100;
- Xwrite_int:
- X new_fmt[new_fmt_lng++] = 'd';
- X new_fmt[new_fmt_lng] = '\0';
- X sprintf(out,new_fmt,ivalue);
- X out = str + strlen(str);
- X break;
- X case 'Y': /* full year value */
- X ivalue = date.Dyear;
- X goto write_int;
- X
- X case 'm': /* month */
- X ivalue = date.Dmonth;
- X goto write_int;
- X
- X case 'M': /* month name */
- X svalue = calendar[date.Dmonth - 1].Mname;
- Xwrite_str:
- X new_fmt[new_fmt_lng++] = 's';
- X new_fmt[new_fmt_lng] = '\0';
- X sprintf(out,new_fmt,svalue);
- X out = str + strlen(str);
- X break;
- X
- X case 'd': /* day */
- X ivalue = date.Dday;
- X goto write_int;
- X
- X case 'D': /* day name */
- X svalue = dayNames[d[0] % DAYS_PER_WEEK];
- X goto write_str;
- X
- X case 'h': /* hour */
- X ivalue = date.Dhour;
- X goto write_int;
- X
- X case 'H': /* hour in 12 hour notation */
- X ivalue = date.Dhour;
- X if (ivalue >= 12) ivalue -= 12;
- X goto write_int;
- X
- X case 'i': /* AM/PM indicator */
- X case 'I':
- X if (date.Dhour >= 12)
- X svalue = "PM";
- X else
- X svalue = "AM";
- X goto write_str;
- X
- X case 'n': /* minutes */
- X case 'N':
- X ivalue = date.Dminute;
- X goto write_int;
- X
- X case 's': /* seconds */
- X case 'S':
- X ivalue = date.Dsecond;
- X goto write_int;
- X
- X default:
- X /* We are in deep caca - don't know what to do with this
- X * format character. Copy the raw format string to the
- X * output as debugging information.
- X */
- X new_fmt[new_fmt_lng++] = fc;
- X new_fmt[new_fmt_lng] = '\0';
- X strcat(out, new_fmt);
- X out = out + strlen(out); /* advance string pointer */
- X break;
- X }
- X }
- X else
- X *out++ = fc; /* copy literal character */
- X }
- X *out = '\0'; /* terminating null */
- X}
- X
- X/* FUNCTION
- X StrToDS - convert a string to a DateStamp.
- X
- X SYNOPSIS
- X int StrToDS(string, date)
- X char *string;
- X struct DateStamp *date;
- X
- X DESCRIPTION
- X StrToDS expects its string argument to contain a date in
- X MM/DD/YY HH:MM:SS format. The time portion is optional.
- X StrToDS will attempt to convert the string to a DateStamp
- X representation. If successful, it will return 0. On
- X failure, a 1 is returned.
- X
- X */
- X
- Xint
- XStrToDS(str, d)
- X char *str; long *d;
- X{
- X register char c;
- X int count;
- X int i, item;
- X DATE date; /* unpacked DateStamp */
- X char *s;
- X
- X int values[3];
- X int value;
- X
- X s = str;
- X for (item = 0; item < 2; ++item) { /* item = date, then time */
- X for (i = 0; i < 3; ++i) values[i] = 0;
- X count = 0;
- X while (c = *s++) { /* get date value */
- X if (c <= ' ')
- X break;
- X
- X if (isdigit(c)) {
- X value = 0;
- X do {
- X value = value*10 + c - '0';
- X c = *s++;
- X } while (isdigit(c));
- X if (count == 3) {
- X bad_value:
- X#ifdef DEBUG
- X puts("Error in date-time format.\n");
- X printf("at %s: values(%d) = %d, %d, %d\n",
- X s, count, values[0], values[1], values[2]);
- X#endif
- X return 1;
- X }
- X values[count++] = value;
- X if (c <= ' ')
- X break;
- X }
- X else if (! strchr(DATE_SEPARATORS, c) )
- X goto bad_value; /* Illegal character - quit. */
- X } /* end while */
- X if (item) { /* Getting time? */
- X date.Dhour = values[0];
- X date.Dminute = values[1];
- X date.Dsecond = values[2];
- X }
- X else { /* Getting date? */
- X
- X/* It's OK to have a null date string, but it's not OK to specify only
- X 1 or 2 of the date components.
- X */
- X if (count && count != 3)
- X goto bad_value;
- X date.Dmonth = values[0];
- X date.Dday = values[1];
- X date.Dyear = values[2];
- X if (date.Dyear == 0) {
- X date.Dyear = START_YEAR;
- X date.Dday = 1;
- X }
- X else {
- X if (date.Dyear < (START_YEAR - 1900) )
- X date.Dyear += 100;
- X date.Dyear += 1900;
- X }
- X }
- X } /* end for */
- X DateToDS(&date, d);
- X return 0;
- X} /* StrToDS */
- X
- X
- X#ifdef DEBUG
- X#include "stdio.h"
- Xmain(ac, av)
- X int ac;
- X char **av;
- X{
- X long datestamp[3]; /* A little dangerous with Aztec */
- X long datestamp2[3];
- X DATE date, oldDate;
- X long day, lastDay;
- X int errors = 0;
- X
- X /*
- X * display results from DateStamp() (hours:minutes:seconds)
- X */
- X DateStamp(datestamp);
- X
- X /*
- X * display results from DSToDate() (e.g. "03-May-88")
- X */
- X DSToDate(datestamp, &date);
- X printf("Current date: %02d-%s-%02d\n",
- X date.Dday, calendar[ date.Dmonth - 1].Mname,
- X (date.Dyear % YEARS_PER_CENTURY));
- X
- X printf("Current time: %02d:%02d:%02d\n",
- X date.Dhour, date.Dminute, date.Dsecond);
- X
- X printf("\nDoing sanity check through year 2000...\n\t");
- X lastDay = (2000L - START_YEAR) * 365L;
- X lastDay += (2000L - START_YEAR) / YEARS_PER_LEAP;
- X for (day = 0; day <= lastDay; ++day) {
- X if (day % 1000 == 0) {
- X printf(" %ld", day);
- X fflush(stdout);
- X }
- X datestamp[0] = day;
- X datestamp[1] = MINS_PER_HOUR - 1;
- X datestamp[2] = TICS_PER_SEC * (SECS_PER_MIN - 1);
- X DSToDate(datestamp, &date);
- X if (day && date == oldDate) {
- X printf("Got same date for days %d, %d: %02d-%s-%02d\n",
- X day - 1, day,
- X date.Dday,
- X calendar[ date.Dmonth - 1 ].Mname,
- X (date.Dyear % YEARS_PER_CENTURY));
- X
- X if (++errors == 10)
- X exit(1);
- X }
- X DateToDS(&date, datestamp2);
- X if (day != datestamp2[0]) {
- X printf("\nConversion mismatch at day %ld!\n", day);
- X printf("\tBad value = %ld", datestamp2[0]);
- X printf("\tDate: %02d-%s-%02d\n",
- X date.Dday,
- X calendar[ date.Dmonth -1 ].Mname,
- X (date.Dyear % YEARS_PER_CENTURY));
- X if (++errors == 10)
- X exit(1);
- X }
- X oldDate = date;
- X }
- X printf("\nSanity check passed.\n");
- X} /* main() */
- X#endif
- X
- END_OF_FILE
- if test 15280 -ne `wc -c <'MRDates.c'`; then
- echo shar: \"'MRDates.c'\" unpacked with wrong size!
- fi
- # end of 'MRDates.c'
- fi
- if test -f 'MRDates.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'MRDates.h'\"
- else
- echo shar: Extracting \"'MRDates.h'\" \(1183 characters\)
- sed "s/^X//" >'MRDates.h' <<'END_OF_FILE'
- X/* MRDates.h - Declarations for types and variables used by MRDates. */
- X
- X#ifndef MRDATES_H
- X#define MRDATES_H 1
- X
- Xtypedef struct {
- X int Dyear; /* year AD (e.g. 1987) */
- X int Dmonth; /* month of year (0-11) */
- X int Dday; /* day in month (1-31) */
- X int Dhour; /* 0-23 */
- X int Dminute; /* 0-59 */
- X int Dsecond; /* 0-59 */
- X int Dweekday; /* day of week (Sun=0) */
- X} DATE;
- X
- Xtypedef struct {
- X char *Mname;
- X int Mdays;
- X } CalEntry;
- X
- X#ifdef MRDATES
- XCalEntry calendar[12] = {
- X { "Jan", 31 }, { "Feb", 28 }, { "Mar", 31 }, { "Apr", 30 },
- X { "May", 31 }, { "Jun", 30 }, { "Jul", 31 }, { "Aug", 31 },
- X { "Sep", 30 }, { "Oct", 31 }, { "Nov", 30 }, { "Dec", 31 }
- X };
- X#else
- Xextern CalEntry calendar[12];
- X#endif
- X
- X#ifdef MRDATES
- Xchar *dayNames[7] = {
- X "Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"
- X };
- X#else
- Xextern char *dayNames[7];
- X#endif
- X
- X/* mrdates.c */
- Xint DSToDate(long *ds, DATE *date);
- Xint DateToDS(DATE *date, long *ds);
- Xint CompareDS(long *d1, long *d2);
- Xvoid DSToStr(char *str, char *fmt, long *d);
- Xint StrToDS(char *str, long *d);
- X
- X#endif /* MRDATES_H */
- END_OF_FILE
- if test 1183 -ne `wc -c <'MRDates.h'`; then
- echo shar: \"'MRDates.h'\" unpacked with wrong size!
- fi
- # end of 'MRDates.h'
- fi
- if test ! -d 'dir1' ; then
- echo shar: Creating directory \"'dir1'\"
- mkdir 'dir1'
- fi
- if test -f 'dir1/File1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'dir1/File1'\"
- else
- echo shar: Extracting \"'dir1/File1'\" \(18 characters\)
- sed "s/^X//" >'dir1/File1' <<'END_OF_FILE'
- XThis is file 1.
- X
- X
- END_OF_FILE
- if test 18 -ne `wc -c <'dir1/File1'`; then
- echo shar: \"'dir1/File1'\" unpacked with wrong size!
- fi
- # end of 'dir1/File1'
- fi
- if test -f 'dir1/File3' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'dir1/File3'\"
- else
- echo shar: Extracting \"'dir1/File3'\" \(18 characters\)
- sed "s/^X//" >'dir1/File3' <<'END_OF_FILE'
- XThis is file 3.
- X
- X
- END_OF_FILE
- if test 18 -ne `wc -c <'dir1/File3'`; then
- echo shar: \"'dir1/File3'\" unpacked with wrong size!
- fi
- # end of 'dir1/File3'
- fi
- if test ! -d 'dir1/Level2' ; then
- echo shar: Creating directory \"'dir1/Level2'\"
- mkdir 'dir1/Level2'
- fi
- if test -f 'dir1/Level2/File1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'dir1/Level2/File1'\"
- else
- echo shar: Extracting \"'dir1/Level2/File1'\" \(81 characters\)
- sed "s/^X//" >'dir1/Level2/File1' <<'END_OF_FILE'
- XThis is file 1.
- XIt is longer than the equivalent file in the other directory.
- X
- X
- X
- END_OF_FILE
- if test 81 -ne `wc -c <'dir1/Level2/File1'`; then
- echo shar: \"'dir1/Level2/File1'\" unpacked with wrong size!
- fi
- # end of 'dir1/Level2/File1'
- fi
- if test -f 'dir1/Level2/File3' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'dir1/Level2/File3'\"
- else
- echo shar: Extracting \"'dir1/Level2/File3'\" \(18 characters\)
- sed "s/^X//" >'dir1/Level2/File3' <<'END_OF_FILE'
- XThis is file 3.
- X
- X
- END_OF_FILE
- if test 18 -ne `wc -c <'dir1/Level2/File3'`; then
- echo shar: \"'dir1/Level2/File3'\" unpacked with wrong size!
- fi
- # end of 'dir1/Level2/File3'
- fi
- if test ! -d 'dir1/Level2/Level3' ; then
- echo shar: Creating directory \"'dir1/Level2/Level3'\"
- mkdir 'dir1/Level2/Level3'
- fi
- if test -f 'dir1/Level2/Level3/File1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'dir1/Level2/Level3/File1'\"
- else
- echo shar: Extracting \"'dir1/Level2/Level3/File1'\" \(18 characters\)
- sed "s/^X//" >'dir1/Level2/Level3/File1' <<'END_OF_FILE'
- XThis is file 1.
- X
- X
- END_OF_FILE
- if test 18 -ne `wc -c <'dir1/Level2/Level3/File1'`; then
- echo shar: \"'dir1/Level2/Level3/File1'\" unpacked with wrong size!
- fi
- # end of 'dir1/Level2/Level3/File1'
- fi
- if test -f 'dir1/Level2/Level3/File2' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'dir1/Level2/Level3/File2'\"
- else
- echo shar: Extracting \"'dir1/Level2/Level3/File2'\" \(18 characters\)
- sed "s/^X//" >'dir1/Level2/Level3/File2' <<'END_OF_FILE'
- XThis is file 2.
- X
- X
- END_OF_FILE
- if test 18 -ne `wc -c <'dir1/Level2/Level3/File2'`; then
- echo shar: \"'dir1/Level2/Level3/File2'\" unpacked with wrong size!
- fi
- # end of 'dir1/Level2/Level3/File2'
- fi
- if test -f 'dir1/Level2/Level3/File3' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'dir1/Level2/Level3/File3'\"
- else
- echo shar: Extracting \"'dir1/Level2/Level3/File3'\" \(18 characters\)
- sed "s/^X//" >'dir1/Level2/Level3/File3' <<'END_OF_FILE'
- XThis is file 3.
- X
- X
- END_OF_FILE
- if test 18 -ne `wc -c <'dir1/Level2/Level3/File3'`; then
- echo shar: \"'dir1/Level2/Level3/File3'\" unpacked with wrong size!
- fi
- # end of 'dir1/Level2/Level3/File3'
- fi
- if test -f 'dir1/file2' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'dir1/file2'\"
- else
- echo shar: Extracting \"'dir1/file2'\" \(18 characters\)
- sed "s/^X//" >'dir1/file2' <<'END_OF_FILE'
- XThis is dile 2.
- X
- X
- END_OF_FILE
- if test 18 -ne `wc -c <'dir1/file2'`; then
- echo shar: \"'dir1/file2'\" unpacked with wrong size!
- fi
- # end of 'dir1/file2'
- fi
- if test ! -d 'dir2' ; then
- echo shar: Creating directory \"'dir2'\"
- mkdir 'dir2'
- fi
- if test -f 'dir2/DifferentType' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'dir2/DifferentType'\"
- else
- echo shar: Extracting \"'dir2/DifferentType'\" \(0 characters\)
- sed "s/^X//" >'dir2/DifferentType' <<'END_OF_FILE'
- END_OF_FILE
- if test 0 -ne `wc -c <'dir2/DifferentType'`; then
- echo shar: \"'dir2/DifferentType'\" unpacked with wrong size!
- fi
- # end of 'dir2/DifferentType'
- fi
- if test -f 'dir2/File1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'dir2/File1'\"
- else
- echo shar: Extracting \"'dir2/File1'\" \(18 characters\)
- sed "s/^X//" >'dir2/File1' <<'END_OF_FILE'
- XThis is file 1.
- X
- X
- END_OF_FILE
- if test 18 -ne `wc -c <'dir2/File1'`; then
- echo shar: \"'dir2/File1'\" unpacked with wrong size!
- fi
- # end of 'dir2/File1'
- fi
- if test -f 'dir2/File2' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'dir2/File2'\"
- else
- echo shar: Extracting \"'dir2/File2'\" \(18 characters\)
- sed "s/^X//" >'dir2/File2' <<'END_OF_FILE'
- XThis is file 2.
- X
- X
- END_OF_FILE
- if test 18 -ne `wc -c <'dir2/File2'`; then
- echo shar: \"'dir2/File2'\" unpacked with wrong size!
- fi
- # end of 'dir2/File2'
- fi
- if test ! -d 'dir2/Level2' ; then
- echo shar: Creating directory \"'dir2/Level2'\"
- mkdir 'dir2/Level2'
- fi
- if test -f 'dir2/Level2/File1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'dir2/Level2/File1'\"
- else
- echo shar: Extracting \"'dir2/Level2/File1'\" \(18 characters\)
- sed "s/^X//" >'dir2/Level2/File1' <<'END_OF_FILE'
- XThis is file 1.
- X
- X
- END_OF_FILE
- if test 18 -ne `wc -c <'dir2/Level2/File1'`; then
- echo shar: \"'dir2/Level2/File1'\" unpacked with wrong size!
- fi
- # end of 'dir2/Level2/File1'
- fi
- if test -f 'dir2/Level2/File2' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'dir2/Level2/File2'\"
- else
- echo shar: Extracting \"'dir2/Level2/File2'\" \(18 characters\)
- sed "s/^X//" >'dir2/Level2/File2' <<'END_OF_FILE'
- XThis is file 2.
- X
- X
- END_OF_FILE
- if test 18 -ne `wc -c <'dir2/Level2/File2'`; then
- echo shar: \"'dir2/Level2/File2'\" unpacked with wrong size!
- fi
- # end of 'dir2/Level2/File2'
- fi
- if test -f 'dir2/Level2/File3' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'dir2/Level2/File3'\"
- else
- echo shar: Extracting \"'dir2/Level2/File3'\" \(18 characters\)
- sed "s/^X//" >'dir2/Level2/File3' <<'END_OF_FILE'
- XThis is file 3.
- X
- X
- END_OF_FILE
- if test 18 -ne `wc -c <'dir2/Level2/File3'`; then
- echo shar: \"'dir2/Level2/File3'\" unpacked with wrong size!
- fi
- # end of 'dir2/Level2/File3'
- fi
- if test ! -d 'dir2/Level2/Level3' ; then
- echo shar: Creating directory \"'dir2/Level2/Level3'\"
- mkdir 'dir2/Level2/Level3'
- fi
- if test -f 'dir2/Level2/Level3/File2' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'dir2/Level2/Level3/File2'\"
- else
- echo shar: Extracting \"'dir2/Level2/Level3/File2'\" \(18 characters\)
- sed "s/^X//" >'dir2/Level2/Level3/File2' <<'END_OF_FILE'
- XThis is file 2.
- X
- X
- END_OF_FILE
- if test 18 -ne `wc -c <'dir2/Level2/Level3/File2'`; then
- echo shar: \"'dir2/Level2/Level3/File2'\" unpacked with wrong size!
- fi
- # end of 'dir2/Level2/Level3/File2'
- fi
- if test -f 'dir2/Level2/Level3/File3' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'dir2/Level2/Level3/File3'\"
- else
- echo shar: Extracting \"'dir2/Level2/Level3/File3'\" \(18 characters\)
- sed "s/^X//" >'dir2/Level2/Level3/File3' <<'END_OF_FILE'
- XThis is file 3.
- X
- X
- END_OF_FILE
- if test 18 -ne `wc -c <'dir2/Level2/Level3/File3'`; then
- echo shar: \"'dir2/Level2/Level3/File3'\" unpacked with wrong size!
- fi
- # end of 'dir2/Level2/Level3/File3'
- fi
- if test -f 'dir2/file3' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'dir2/file3'\"
- else
- echo shar: Extracting \"'dir2/file3'\" \(18 characters\)
- sed "s/^X//" >'dir2/file3' <<'END_OF_FILE'
- XThis is file 3.
- X
- X
- END_OF_FILE
- if test 18 -ne `wc -c <'dir2/file3'`; then
- echo shar: \"'dir2/file3'\" unpacked with wrong size!
- fi
- # end of 'dir2/file3'
- fi
- if test -f 'makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'makefile'\"
- else
- echo shar: Extracting \"'makefile'\" \(573 characters\)
- sed "s/^X//" >'makefile' <<'END_OF_FILE'
- X# Aztec C Makefile for DiffDir program
- X
- X#CFLAGS = -bs
- X#LFLAGS = -w -g
- X
- XCFLAGS= -so
- XLFLAGS=
- X
- XOBJ = DiffDir.o MRDates.o
- X
- XDiffDir: $(OBJ)
- X ln $(LFLAGS) -o DiffDir $(OBJ) -lc
- X
- XDiffDir.o: DiffDir.c MRDates.h
- X
- Xclean:
- X delete (#?.o|#?.dbg)
- X
- XSRC = DiffDir.c MRDates.h MRDates.c Makefile
- XBIN = DiffDir.man DiffDir.n DiffDir Sample.Output
- XMISC= dir1 dir2
- X
- XDiffDir.lzh: $(SRC) $(BIN) $(MISC)
- X delete (diffdir.lzh)
- X lharc -b32 -r -xa a DiffDir $(SRC) dir1/* dir2/*
- X
- Xshar: DiffDir.lzh
- X uuencode >DiffDir.lzu DiffDir.lzh DiffDir.lzh
- X makekit -n SHAR DiffDir.lzu
- X
- END_OF_FILE
- if test 573 -ne `wc -c <'makefile'`; then
- echo shar: \"'makefile'\" unpacked with wrong size!
- fi
- # end of 'makefile'
- fi
- echo shar: End of archive 1 \(of 1\).
- cp /dev/null ark1isdone
- MISSING=""
- for I in 1 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have the archive.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
- --
- Mail submissions (sources or binaries) to <amiga@uunet.uu.net>.
- Mail comments to the moderator at <amiga-request@uunet.uu.net>.
- Post requests for sources, and general discussion to comp.sys.amiga.misc.
-